const http = require('./http.js')

/**
 * 检查录音权限
 * @returns {Promise<void>}
 */
function checkRecordPermission(){
  return new Promise((resolve,reject) =>{
    wx.getSetting({
      success(res){
        if(res.authSetting['scope.record']){
          resolve();
        }else{
          wx.authorize({
            scope: 'scope.record',
            success() { 
              console.log("申请录音权限成功")
              resolve(); 
            },
            fail() { reject(new Error('用户未授予录音权限')); }
          });
        }
      },
      fail(){
        reject(new Error('获取录音权限设置失败'));
      }
    })
  })
}
/**
 * 获取数据，对下拉框进行数据填充（数据量小）
 * @param {String} endpoint - 获取数据的接口地址
 * @param {String} stateKey - 需要赋值的下拉框(页面data中存储该选项的键名)
 * @param {Page} page - 页面实例，用于调用setData
 * @returns {Promise} 返回一个Promise，成功时设置页面数据，失败时reject
 */
function fetchOptions(endpoint, stateKey, page) {
  return new Promise((resolve, reject) => {
    http.get(endpoint).then(res => {
      if (res.data && res.data.code === 200) {
        // 假定接口返回数据格式为数组
        page.setData({ [stateKey]: res.data.data }, resolve);
      }
      else {
        reject('数据加载失败');
      }
    }).catch(err => {
      console.error(`加载 ${stateKey} 数据失败:`, err);
      reject(err);
    });
  });
}

/**
 * 获取数据，对下拉框进行数据填充,针对examSite进行获取
 * @param {String} endpoint - 获取数据的接口地址
 * @param {String} stateKey - 需要赋值的下拉框(页面data中存储该选项的键名)
 * @param {Page} page - 页面实例，用于调用setData
 * @returns {Promise} 返回一个Promise，成功时设置页面数据，失败时reject
 */
function fetchOptions1(endpoint, stateKey, page) {
  return new Promise((resolve, reject) => {
    http.get(endpoint).then(res => {
      if (res.data && res.data.code === 200) {
        // 假定接口返回数据格式为数组
        let data = res.data.data;
        // 为每个报名点信息，增加display属性
        data = data.map(item => {
          return {
            ...item,
            display: item.code + "/" + item.name//用于展示在picker中
          }
        })
        page.setData({ [stateKey]: data }, resolve);
      }
      else {
        reject('数据加载失败');
      }
    }).catch(err => {
      console.error(`加载 ${stateKey} 数据失败:`, err);
      reject(err);
    });
  });
}

/**
 * 获取数据，对下拉框进行数据填充（数据量大）
 * @param {String} endpoint - 获取数据的接口地址
 * @param {String} stateKey - 需要赋值的下拉框(页面data中存储该选项的键名)
 * @param {Page} page - 页面实例，用于调用setData
 * @returns {Promise} 返回一个Promise，成功时设置页面数据，失败时reject
 */
function fetchOptions2(endpoint, stateKey, page) {
  return new Promise((resolve, reject) => {
    http.get(endpoint).then(res => {
      if (res.data && res.data.code === 200) {
        // 假定接口返回数据格式为数组
        page.setData({ [stateKey]: res.data.data.slice(0,2000) }, resolve);
      } else {
        reject('数据加载失败');
      }
    }).catch(err => {
      console.error(`加载 ${stateKey} 数据失败:`, err);
      reject(err);
    });
  });
}

/**
 * 获取数据，对下拉框进行数据填充（针对返回数据存在res.data中，而不是res.data.data中）
 * @param {String} endpoint - 获取数据的接口地址
 * @param {String} stateKey - 需要赋值的下拉框(页面data中存储该选项的键名)
 * @param {Page} page - 页面实例，用于调用setData
 * @returns {Promise} 返回一个Promise，成功时设置页面数据，失败时reject
 */
function fetchOptions3(endpoint, stateKey, page) {
  return new Promise((resolve, reject) => {
    http.get(endpoint).then(res => {
      if (res.data ) {
        // 假定接口返回数据格式为数组
        page.setData({ [stateKey]: res.data }, resolve);
      } else {
        reject('数据加载失败');
      }
    }).catch(err => {
      console.error(`加载 ${stateKey} 数据失败:`, err);
      reject(err);
    });
  });
}

/**
 * 通过id查找下标
 * @param {Array} options 传入的下拉选择框选项数组，每个选项应包含id属性
 * @param {int} id 传入的id值，用于在options中查找对应的下标
 * @returns {int} 返回找到的下标，如果未找到则返回-1
 */
function findIndexById(options, id) {
  return options.findIndex(option => option.id == id) >=0 ? options.findIndex(option => option.id == id) : null;
}

/**
 * 通过code查找下标
 * @param {Array} options 传入的下拉选择框选项数组，每个选项应包含code属性
 * @param {String} code 传入的code值，用于在options中查找对应的下标
 * @returns {int} 返回找到的下标，如果未找到则返回-1
 */
function findIndexByCode(options, code) {
  return options.findIndex(option => option.code == code)>=0? options.findIndex(option => option.code == code) : null;
}

/**
 * 通过cityCode查找下标,专为city设计
 * @param {Array} options 传入的下拉选择框选项数组，每个选项应包含code属性
 * @param {String} code 传入的code值，用于在options中查找对应的下标
 * @returns {int} 返回找到的下标，如果未找到则返回-1
 */
function findIndexByCode2(options, code) {
  return options.findIndex(option => option.cityCode == code)>=0? options.findIndex(option => option.cityCode == code) : null;
}

/**
 * 通过name查找下标
 * @param {Array} options 传入的下拉选择框选项数组，每个选项应包含name属性
 * @param {String} name 传入的name值，用于在options中查找对应的下标
 * @returns {int} 返回找到的下标，如果未找到则返回-1
 */
function findIndexByName(options, name) {
  return options.findIndex(option => option.name == name)>=0 ? options.findIndex(option => option.name == name) : null;
}

/**
 * 通过name查找对应的id
 * @param {Array} options 传入的下拉选择框选项数组，每个选项应包含name和id属性
 * @param {string} name 传入的name值，用于在options中查找对应的id
 * @returns {int} 返回找到的id，如果未找到则返回-1
 */
function findIdByName(options, name) {
  const item = options.find(option => option.name == name);
  return item ? item.id : null;
}

/**
 * 通过name查找对应的id,专为city设计
 * @param {Array} options 传入的下拉选择框选项数组，每个选项应包含name和id属性
 * @param {string} name 传入的name值，用于在options中查找对应的id
 * @returns {int} 返回找到的id，如果未找到则返回-1
 */
function findIdByName2(options, name) {
  const item = options.find(option => option.cityName == name);
  return item ? item.id : null;
}

/**
 * 通过id查找对应的name
 * @param {Array} options 传入的下拉选择框选项数组，每个选项应包含name和id属性
 * @param {string} id 传入的id值，用于在options中查找对应的name
 * @returns {int} 返回找到的name，如果未找到则返回null
 */
function findNameById(options, id) {
  const item = options.find(option => option.id === id);
  return item ? item.name : null;
}

/**
 * 通过name查找对应的code
 * @param {Array} options 传入的下拉选择框选项数组，每个选项应包含name和code属性
 * @param {string} name 传入的name值，用于在options中查找对应的code
 * @returns {string} 返回找到的code，如果未找到则返回null
 */
function findCodeByName(options, name) {
  const item = options.find(option => option.name == name);
  return item ? item.code : null;
}

/**
 * 通过name查找对应的code，专为city设计
 * @param {Array} options 传入的下拉选择框选项数组，每个选项应包含name和code属性
 * @param {string} name 传入的name值，用于在options中查找对应的code
 * @returns {string} 返回找到的code，如果未找到则返回null
 */
function findCodeByName2(options, name) {
  const item = options.find(option => option.cityName == name);
  return item ? item.cityCode : null;
}

/**
 * 检查指定字段的数据是否发生变化
 * @param {Object} newData - 新数据对象（当前表单数据）
 * @param {Object} storedData - 已存储的数据对象（本地存储/旧数据）
 * @param {Array<string>} fieldsToCheck - 需要比较的字段名数组
 * @returns {boolean} - 返回true表示数据有变化，false表示无变化
 */
function checkDataChanged(newData, storedData, fieldsToCheck) {
  // 遍历所有需要检查的字段
  if(!storedData[fieldsToCheck[0]]) return true;
  for (const field of fieldsToCheck) {
    // 严格比较新旧数据的每个字段值
    if (newData[field] !== storedData[field]) {
      // 发现任意一个字段值不同，立即返回true（变化）
      return true; 
    }
  }
  // 所有字段比较完毕未发现变化，返回false
  return false; 
}

/**
 * 分割并存储报名数据
 * 
 * 该函数根据不同的考试类型，将后端返回的报名数据分割为学籍基础信息和考试报考信息，
 * 并将分割后的数据保存到本地存储中，以便后续页面使用。
 * 
 * @param {string} examType - 考试类型标识符，支持以下值：
 *   'gk' - 高考
 *   'ck' - 成考
 *   'zsb' - 专升本
 *   'zhongkao' - 中考
 *   'zikao' - 自考
 * @param {Object} backendData - 后端返回的原始报名数据对象
 * 
 * 函数逻辑：
 * 1. 根据考试类型选择不同的数据处理逻辑
 * 2. 将原始数据分割为学籍基础信息(academic_info)和考试报考信息(exam_info)
 * 3. 为每个字段提供默认值，防止undefined错误
 * 4. 使用wx.setStorageSync将处理后的数据保存到本地存储
 * 
 * 存储键名约定：
 * - 高考: gk_academic_info 和 gk_exam_info
 * - 成考: ck_academic_info 和 ck_exam_info
 * - 其他考试: {examType}_exam_registrationInfo
 */
function splitAndStoreRegistrationData(examType, backendData) {
  switch(examType) {
    case 'gk': // 高考数据处理
      // 提取学籍基础信息
      console.log(backendData)
      const gk_academic_info = {
        city_code: backendData.cityCode || '', // 改为驼峰式
        county_code: backendData.countyCode || '', // 改为驼峰式
        registration_point_code: backendData.registrationPointCode || '', // 改为驼峰式
        graduate_type_id: backendData.graduateTypeId || '', // 改为驼峰式
        graduate_school_name: backendData.graduateSchoolName || '', // 改为驼峰式
        graduate_class: backendData.graduateClass || '', // 改为驼峰式
        study_school_name: backendData.studySchoolName || '', // 改为驼峰式
        study_class: backendData.studyClass || '', // 改为驼峰式
        registration_authority: backendData.registrationAuthority || '', // 改为驼峰式
        registered_residence_code: backendData.registeredResidenceCode || '', // 改为驼峰式
        household_immigration: backendData.householdImmigration || 0, // 改为驼峰式
        household_immigration_date: backendData.householdImmigrationDate || '', // 改为驼峰式
        migrant_children: backendData.migrantChildren || 0 // 改为驼峰式
      };
      // 提取考试报考信息
      const gk_exam_info = {
        exam_type: backendData.examType || '', // 改为驼峰式
        apply_type: backendData.applyType || '', // 改为驼峰式
        candidate_type_code: backendData.candidateTypeCode || '',
        foreign_language_test_id: backendData.foreignLanguageTestId || 0, // 改为驼峰式
        promise_junior_college: backendData.promiseJuniorCollege || 0, // 改为驼峰式
        national_special: backendData.nationalSpecial || 0, // 改为驼峰式
        university_special: backendData.universitySpecial || 0, // 改为驼峰式
        local_special: backendData.localSpecial || 0, // 改为驼峰式
        free_medical_orientation: backendData.freeMedicalOrientation || 0, // 改为驼峰式
        mailing_address: backendData.mailingAddress || '', // 改为驼峰式
        postal_code: backendData.postalCode || '', // 改为驼峰式
        recipient_name: backendData.recipientName || '', // 改为驼峰式
        recipient_phone: backendData.recipientPhone || '' // 改为驼峰式
      };
      // 保存到本地存储
      wx.setStorageSync('gk_academic_info', gk_academic_info);
      wx.setStorageSync('gk_exam_info', gk_exam_info);
      break;

    case 'ck': // 成人高考数据处理
      // 提取学籍基础信息
      const ck_academic_info = {
        education_level: backendData.culturalLevelId || '',
        diploma_number: backendData.graduationCertificateNo || '',
        graduation_type: backendData.graduationTypeId || '',
        graduation_school: backendData.schoolId || '',
        graduation_date: backendData.graduationDate || '',
        job_category: backendData.occupationId || '',
        is_working: backendData.isEmployed || '',
        work_location: backendData.isEmployed === '是' ? backendData.workLocation || '' : '',
        work_name: backendData.isEmployed === '是' ? backendData.workUnitName || '' : '',
        work_start_date: backendData.isEmployed === '是' ? backendData.employmentDate || '' : ''
      };
      // 提取考试报考信息
      const ck_exam_info = {
        exam_type: backendData.examTypeId || '',
        outside_residence: backendData.outsideResidenceId || '',
        military_service: backendData.militaryServiceId || '',
        household_location: backendData.householdLocation || '',
        candidate_feature: backendData.candidateFeatureId || '',
        admission_category: backendData.admissionCategoryId || '',
        exam_level: backendData.examLevelId || '',
        exam_subject: backendData.examSubjectId || '',
        study_location: backendData.studyLocationId || '',
        study_mode: backendData.studyModeId || '',
        exam_site_id: backendData.examSiteId || '',
        postal_code: backendData.postalCode || '',
        ck_exam_university_school: backendData.examUniversityId || '',
        ck_major: backendData.majorId || '',
        emergency_contact: backendData.emergencyContact || ''
      };
      // 保存到本地存储
      wx.setStorageSync('ck_academic_info', ck_academic_info);
      wx.setStorageSync('ck_exam_info', ck_exam_info);
      break;

    case 'zsb':  // 处理专升本数据
      // 1. 基础候选人信息
      // const base_candidate_info = {
      //   id: backendData.id,
      //   id_number: backendData.idNumber,
      //   name: backendData.name,
      //   gender: backendData.gender,
      //   birth_date: backendData.birthDate,
      //   ethnicity_id: backendData.ethnicityId,
      //   political_status_id: backendData.politicalStatusId,
      //   foreign_language_id: backendData.foreignLanguageId,
      //   phone: backendData.phone,
      //   password: backendData.password
      // };
      // 2. 报名详情 （志愿／专业等）
      const baoming_candidate_info = {
        id_number: backendData.idNumber,
        vocational_college_id: backendData.vocationalCollegeId,
        vocational_major_id: backendData.vocationalMajorId,
        candidate_type_id: backendData.candidateTypeId,
        exam_center_city_id: backendData.examCenterCityId,
        exam_major_id: backendData.examMajorId,
        volunteer_college_id: backendData.volunteerCollegeId,
        volunteer_major_id: backendData.volunteerMajorId,
        is_certificate_issued: backendData.isCertificateIssued
      };
      // 3. 邮寄／证书信息
      const post_candidate_info = {
        id_number: backendData.idNumber,
        address: backendData.address,
        postal_code: backendData.postalCode,
        recipient_name: backendData.recipientName,
        is_certificate_issued: backendData.isCertificateIssued
      };
      // 存本地
      // wx.setStorageSync('base_candidate_info', base_candidate_info);
      wx.setStorageSync('baoming_candidate_info', baoming_candidate_info);
      wx.setStorageSync('post_candidate_info', post_candidate_info);
      break;

    case 'zk': // 中考数据处理（
      const zk_exam_info = {
        candidate_category_code: backendData.candidateCategoryCode || '',
        candidate_type_code: backendData.candidateTypeCode || '',
        registration_site_code: backendData.registrationSiteCode || '',
        graduation_school_code: backendData.graduationSchoolCode || '',
        schooling_length: backendData.schoolingLength || '',
        mailing_address: backendData.mailingAddress || '',
        postal_code: backendData.postalCode || '',
        special_skills: backendData.specialSkills || '',
        work_school_code: backendData.workSchoolCode || '',
        junior_position: backendData.juniorPosition || ''
      };
      wx.setStorageSync('zk_exam_info', zk_exam_info);
      break;

    case 'zikao': // 自考数据处理
      // 学籍信息对象（仅编码）
      const zikao_academic_info = {
        english_name:            backendData.englishName || '',
        registered_residence_code: backendData.registeredResidenceCode || '',
        pre_education_code:      backendData.preEducationCode || '',
        occupation_code:         backendData.occupationCode || '',
        major_code:              backendData.majorCode || '',
        registration_city_code:  backendData.registrationCityCode || '',
        registration_point_code: backendData.registrationPointCode || '',
        is_currently_student:    backendData.isCurrentlyStudent || 0,
        household_address:       backendData.householdAddress || ''
      };
    
      // 补充报名信息（仅必要字段）
      const zikao_exam_extra = {
        office_phone:            backendData.officePhone || '',
        postal_code:             backendData.postalCode || '',
        address:                 backendData.address || '',
        mobile_phone2:           backendData.mobilePhone2 || '',
        work_unit:               backendData.workUnit || '',
        email:                   backendData.email || '',
        work_unit_address:       backendData.workUnitAddress || '',
        current_residence:       backendData.currentResidence || '',
        police_school_student_id: backendData.policeSchoolStudentId || '',
        police_officer_number:   backendData.policeOfficerNumber || '',
        registration_time:       backendData.registrationTime || '',
        police_review_flag:      backendData.policeReviewFlag || 0,
        attend_exam_punctually:  backendData.attendExamPunctually || 1
      };
    
      // 保存到本地存储
      wx.setStorageSync('zikao_academic_info', zikao_academic_info);
      wx.setStorageSync('zikao_exam_extra', zikao_exam_extra);
      break;

    default:
      console.warn(`未知的考试类型: ${examType}`);
  }
}

/**
 * 加载并处理考生的报名信息
 * 
 * 该函数通过考生的身份证号从后端获取报名信息，并根据不同的考试类型（专升本、成考、高考）
 * 调用分割存储函数处理数据，将处理后的结果保存到本地存储中。
 * 
 * @param {string} idNumber - 考生的身份证号码，作为请求参数
 * 
 * 函数流程：
 * 1. 构建请求URL，使用考生的身份证号作为路径参数
 * 2. 发送GET请求获取报名信息
 * 3. 检查响应数据中存在的考试类型：
 *    - 专升本考试(zsb_exam)
 *    - 成考(ck_exam)
 *    - 高考(gk_exam)
 * 4. 对每种存在的考试类型，调用分割存储函数处理数据
 * 5. 错误处理：请求失败时显示错误提示
 * 
 * 注意事项：
 * - 使用统一的工具函数 `tools.splitAndStoreRegistrationData` 处理不同考试类型的数据
 * - 函数不会返回任何值，处理结果直接保存到本地存储
 * - 错误处理使用微信小程序的 showToast API 显示简单提示
 */
function loadExamInfo(idNumber){
  // 获取报名信息
  return new Promise((resolve,reject) => {
    const url = `/baoming/candidate/examInfo/${idNumber}`
  http.get(url).then(res =>{
      console.log(res)
      const data = res.data.data;
      // 对专升本考试进行处理
      if(data.zsb_exam){
          this.splitAndStoreRegistrationData('zsb', data.zsb_exam);
      }
      // 对成考信息处理
      if(data.ck_exam){
        this.splitAndStoreRegistrationData('ck', data.ck_exam);
      }
      // 对成考信息处理
      if (data.gk_exam) {
        this.splitAndStoreRegistrationData('gk', data.gk_exam);
      }
      // 对中考信息处理
      if (data.zk_exam) {
        this.splitAndStoreRegistrationData('zk', data.zk_exam);
      }
      // 对自考信息处理
      if (data.zikao_exam) {
        this.splitAndStoreRegistrationData('zikao', data.zikao_exam);
      }
      resolve();
  }).catch(err =>{
      console.log(err)
      wx.showToast({
        title: '发生未知错误',
      })
      reject(err);
  })
  })
}

 /**
   * 日期格式化函数（用于将日期格式化为 YYYY-MM-DD）
   * @param {string} dateString -需要格式化的日期字符串
   * @return {string} 格式化后的日期字符串
   */
function formatDate(dateString) {
    if (!dateString) return '';
    const date = new Date(dateString);
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
}

// 校验函数
function validateCandidateInfo(base_candidate_info, needCheckPassword = false) {
  const errors = [];
  const {
    id_number,
    name,
    gender,
    birth_date,
    ethnicity_id,
    political_status_id,
    foreign_language_id,
    phone,
    password,
  } = base_candidate_info;

  // === 基本字段校验 ===
  if (!id_number) errors.push("身份证号不能为空");
  else if (!/^[1-9]\d{16}[\dXx]$/.test(id_number))
    errors.push("身份证号格式不正确");

  if (!name) errors.push("姓名不能为空");

  if (!gender || !["男", "女"].includes(gender)) {
    errors.push("请选择性别");
  }

  if (!birth_date) errors.push("请选择出生日期");

  // === 只校验非空 ===
  if (!ethnicity_id) errors.push("请选择民族");
  if (!political_status_id) errors.push("请选择政治面貌");
  if (!foreign_language_id) errors.push("请选择外语种类");

  // === 手机号校验 ===
  if (!phone) errors.push("手机号不能为空");
  else if (!/^1[3-9]\d{9}$/.test(phone))
    errors.push("手机号格式不正确");

  // === 密码校验（根据传入参数决定是否校验） ===
  if (needCheckPassword) {
    if (!password) errors.push("密码不能为空");
    else if (password.length < 6) errors.push("密码长度必须大于6位");
  }

  // === 错误提示 ===
  if (errors.length > 0) {
    wx.showToast({
      title: errors[0],
      icon: "none",
      duration: 2000,
    });
  }

  return errors;
}

module.exports = {
  checkRecordPermission : checkRecordPermission,
  fetchOptions : fetchOptions,
  fetchOptions1 : fetchOptions1,
  fetchOptions2 : fetchOptions2,
  fetchOptions3 : fetchOptions3,
  findIndexById : findIndexById,
  findIndexByCode : findIndexByCode,
  findIndexByCode2 : findIndexByCode2,
  findIdByName : findIdByName,
  findIdByName2 : findIdByName2,
  findNameById : findNameById,
  findCodeByName : findCodeByName,
  findCodeByName2 : findCodeByName2,
  findIndexByName : findIndexByName,
  checkDataChanged : checkDataChanged,
  splitAndStoreRegistrationData : splitAndStoreRegistrationData,
  loadExamInfo : loadExamInfo,
  formatDate : formatDate,
  validateCandidateInfo: validateCandidateInfo
}